package com.zengqingfa.producerconsumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @fileName: ConsumerProducerWithBlockingQueueTest2
 * @author: zengqingfa
 * @date: 2022/12/14 16:34
 * @description:
 */
public class ConsumerProducerWithBlockingCondition {

    private Queue queue;

    private int maxSize = 10;

    private ReentrantLock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public ConsumerProducerWithBlockingCondition() {
        this.queue = new LinkedList();
    }

    /**
     * 往队列加数据
     *
     * @param object
     */
    public void put(Object object) {
        lock.lock();
        try {
            while (queue.size() == maxSize) {
                //队列已满
                notFull.await();
            }
            queue.add(object);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 从队列中获取数据
     *
     * @return
     */
    public Object take() {
        lock.lock();
        Object remove = null;
        try {
            while (queue.isEmpty()) {
                //队列已满
                notEmpty.await();
            }
            remove = queue.remove();
            notFull.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return remove;
    }

    public static void main(String[] args) {
        ConsumerProducerWithBlockingCondition condition = new ConsumerProducerWithBlockingCondition();
        Producer producer = condition.new Producer(condition);
        Consumer consumer = condition.new Consumer(condition);
        producer.start();
        consumer.start();
    }

    class Consumer extends Thread {

        private ConsumerProducerWithBlockingCondition condition;

        public Consumer(ConsumerProducerWithBlockingCondition condition) {
            this.condition = condition;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 100; i++) {
                    System.out.println("取出队列数据：" + condition.take() + ",仓库还有：" + queue.size());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class Producer extends Thread {

        private ConsumerProducerWithBlockingCondition condition;

        public Producer(ConsumerProducerWithBlockingCondition condition) {
            this.condition = condition;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 100; i++) {
                    System.out.println("生产者放入队列：" + i);
                    condition.put(i);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
